#ifndef GAME_MATH_H
#define GAME_MATH_H
#include <climits>
#include <cmath>
#include "game_platform.h"
#include "game_intrinsicts.h"
#include "game_debug_interface.h"

// 计算给定浮点数的平方根
inline real32 SquareRoot(real32 Real32) {
    // 计算输入值的平方根
    real32 Result = sqrtf(Real32);

    // 返回计算出的平方根
    return Result;
}

// 计算并返回输入向量 A 的垂直向量
inline v2 Perp(v2 A) {
    // 创建一个新的向量 Result，其 x 分量为 -A.y，y 分量为 A.x
    // 这样得到的结果是 A 的垂直向量，遵循二维空间的垂直关系
    v2 Result{-A.y, A.x};

    // 返回计算得到的垂直向量
    return Result;
}

// 定义一个内联函数，将整数类型 (int32) 转换为 v2 类型的向量
inline v2 v2i(int32 X, int32 Y) {
    // 将整数类型的 X 和 Y 转换为实数类型 (real32)，并返回作为 v2 向量
    v2 Result = {(real32)X, (real32)Y};
    return Result;
}

// 定义一个内联函数，将无符号整数类型 (uint32) 转换为 v2 类型的向量
inline v2 v2i(uint32 X, uint32 Y) {
    // 将无符号整数类型的 X 和 Y 转换为实数类型 (real32)，并返回作为 v2 向量
    v2 Result = {(real32)X, (real32)Y};
    return Result;
}

// 工厂函数，用于创建一个 v2 对象
inline v2 V2(real32 X, real32 Y) {
    v2 Result;
    Result.x = X;
    Result.y = Y;
    return Result;
}

// 工厂函数，用于创建一个 v3 对象
inline v3 V3(real32 X, real32 Y, real32 Z) {
    v3 Result;
    Result.x = X;
    Result.y = Y;
    Result.z = Z;
    return Result;
}

inline v3 V3(v2 XY, real32 Z) {
    v3 Result;
    Result.x = XY.x;
    Result.y = XY.y;
    Result.z = Z;
    return Result;
}

// 工厂函数，用于创建一个 v4 对象
inline v4 V4(real32 X, real32 Y, real32 Z, real32 W) {
    v4 Result;
    Result.x = X;
    Result.y = Y;
    Result.z = Z;
    Result.w = W;
    return Result;
}

// 重载二元运算符 * 实现向量与标量的乘法
inline v2 operator*(v2 A, real32 B) {
    v2 Result;
    Result.x = B * A.x;
    Result.y = B * A.y;
    return Result;
}

// 重载二元运算符 * 实现标量与向量的乘法
inline v2 operator*(real32 A, v2 B) {
    v2 Result;
    Result.x = A * B.x;
    Result.y = A * B.y;
    return Result;
}

// 重载 *= 运算符，实现向量与标量的乘法赋值
inline v2& operator*=(v2& A, real32 B) {
    A = A * B;  // 复用已定义的乘法操作
    return A;
}

// 重载一元运算符 - 实现向量取反
inline v2 operator-(v2 A) {
    v2 Result;
    Result.x = -A.x;
    Result.y = -A.y;
    return Result;
}

// 重载二元运算符 + 实现向量与向量的加法
inline v2 operator+(v2 A, v2 B) {
    v2 Result;
    Result.x = A.x + B.x;
    Result.y = A.y + B.y;
    return Result;
}

// 重载二元运算符 + 实现标量与向量的加法
inline v2 operator+(real32 A, v2 B) {
    v2 Result;
    Result.x = A + B.x;
    Result.y = A + B.y;
    return Result;
}

// 重载 += 运算符，实现向量与标量的加法赋值
inline v2& operator+=(v2& A, real32 B) {
    A = B + A;  // 复用已定义的加法操作
    return A;
}

// 重载 += 运算符，实现向量与向量的加法赋值
inline v2& operator+=(v2& A, v2 B) {
    A = B + A;  // 复用已定义的加法操作
    return A;
}

// 重载二元运算符 - 实现向量与向量的减法
inline v2 operator-(v2 A, v2 B) {
    v2 Result;
    Result.x = A.x - B.x;
    Result.y = A.y - B.y;
    return Result;
}

// 重载二元运算符 - 实现向量与标量的减法
inline v2 operator-(v2 A, real32 B) {
    v2 Result;
    Result.x = A.x - B;
    Result.y = A.y - B;
    return Result;
}

// 重载 -= 运算符，实现向量与标量的减法赋值
inline v2& operator-=(v2& A, real32 B) {
    A = A - B;  // 复用已定义的减法操作
    return A;
}

// 重载 -= 运算符，实现向量与向量的减法赋值
inline v2& operator-=(v2& A, v2 B) {
    A = B - A;  // 复用已定义的减法操作
    return A;
}

// 计算给定值的平方
inline real32 Square(real32 A) {
    real32 Result = A * A;
    return Result;
}

// 定义一个内联函数 Hadamard，用于计算两个二维向量的阿达玛积（对应分量相乘）。
inline v2 Hadamard(v2 A, v2 B) {
    // 定义结果向量 Result，其 x 分量为 A.x * B.x，y 分量为 A.y * B.y。
    v2 Result = {A.x * B.x, A.y * B.y};

    // 返回计算结果的二维向量 Result。
    return Result;
}

// 计算两个向量的内积
inline real32 Inner(v2 A, v2 B) {
    // 计算A的X分量与B的X分量的乘积
    // 然后加上A的Y分量与B的Y分量的乘积
    real32 Result = A.x * B.x + A.y * B.y;

    // 返回内积的结果
    return Result;
}

inline real32 LengthSq(v2 A) {
    //   这个函数计算向量 A 的长度的平方（即 A
    //   的模的平方），而不是完整的模数。计算长度的平方有时比计算长度本身更高效，因为它避免了求平方根的开销。
    // 使用内积公式：
    //   |A|^2 = A.x^2 + A.y^2
    //   其中 A.x 和 A.y 分别是向量 A 的 x 和 y 坐标。
    real32 Result = Inner(A, A);
    return Result;
}

// Length函数用于计算二维向量A的长度（即大小或幅度）。
inline real32 Length(v2 A) {
    // 计算向量A的平方长度的平方根
    // LengthSq(A)返回向量的平方长度，取平方根即可得到实际的长度
    real32 Result = SquareRoot(LengthSq(A));
    return Result;  // 返回计算出的长度
}

//
// 重载二元运算符 * 实现向量与标量的乘法
inline v3 operator*(v3 A, real32 B) {
    v3 Result;
    Result.x = B * A.x;
    Result.y = B * A.y;
    Result.z = B * A.z;
    return Result;
}

// 重载二元运算符 * 实现标量与向量的乘法
inline v3 operator*(real32 A, v3 B) {
    v3 Result;
    Result.x = A * B.x;
    Result.y = A * B.y;
    Result.z = A * B.z;
    return Result;
}

// 重载二元运算符 * 实现标量与向量的乘法
inline v3 operator*(v3 A, v3 B) {
    v3 Result;
    Result.x = A.x * B.x;
    Result.y = A.y * B.y;
    Result.z = A.z * B.z;
    return Result;
}

// 重载 *= 运算符，实现向量与标量的乘法赋值
inline v3& operator*=(v3& A, real32 B) {
    A = A * B;  // 复用已定义的乘法操作
    return A;
}

// 重载一元运算符 - 实现向量取反
inline v3 operator-(v3 A) {
    v3 Result;
    Result.x = -A.x;
    Result.y = -A.y;
    Result.z = -A.z;
    return Result;
}

// 重载二元运算符 + 实现向量与向量的加法
inline v3 operator+(v3 A, v3 B) {
    v3 Result;
    Result.x = A.x + B.x;
    Result.y = A.y + B.y;
    Result.z = A.z + B.z;
    return Result;
}

inline v3 operator-(v3 A, v3 B) {
    v3 Result;
    Result.x = A.x - B.x;
    Result.y = A.y - B.y;
    Result.z = A.z - B.z;
    return Result;
}

inline v3 operator-=(v3& A, v3 B) {
    A.x = A.x - B.x;
    A.y = A.y - B.y;
    A.z = A.z - B.z;
    return A;
}

// 重载二元运算符 + 实现标量与向量的加法
inline v3 operator+(real32 A, v3 B) {
    v3 Result;
    Result.x = A + B.x;
    Result.y = A + B.y;
    Result.z = A + B.z;
    return Result;
}

// 重载 += 运算符，实现向量与标量的加法赋值
inline v3& operator+=(v3& A, real32 B) {
    A = B + A;  // 复用已定义的加法操作
    return A;
}

// 重载 += 运算符，实现向量与向量的加法赋值
inline v3& operator+=(v3& A, v3 B) {
    A = B + A;  // 复用已定义的加法操作
    return A;
}

// 定义一个内联函数 Hadamard，用于计算两个二维向量的阿达玛积（对应分量相乘）。
inline v3 Hadamard(v3 A, v3 B) {
    // 定义结果向量 Result，其 X 分量为 A.x * B.x，Y 分量为 A.y * B.y。
    v3 Result = {A.x * B.x, A.y * B.y, A.z * B.z};

    // 返回计算结果的二维向量 Result。
    return Result;
}

// 计算两个向量的内积
inline real32 Inner(v3 A, v3 B) {
    // 计算A的X分量与B的X分量的乘积
    // 然后加上A的Y分量与B的Y分量的乘积
    real32 Result = A.x * B.x + A.y * B.y + A.z * B.z;

    // 返回内积的结果
    return Result;
}

inline real32 LengthSq(v3 A) {
    //   这个函数计算向量 A 的长度的平方（即 A
    //   的模的平方），而不是完整的模数。计算长度的平方有时比计算长度本身更高效，因为它避免了求平方根的开销。
    // 使用内积公式：
    //   |A|^2 = A.x^2 + A.y^2 + A.z^2
    //   其中 A.x , A.y, A.z 分别是向量 A 的 x , y,z 坐标。
    real32 Result = Inner(A, A);
    return Result;
}

// Length函数用于计算二维向量A的长度（即大小或幅度）。
inline real32 Length(v3 A) {
    // 计算向量A的平方长度的平方根
    // LengthSq(A)返回向量的平方长度，取平方根即可得到实际的长度
    real32 Result = SquareRoot(LengthSq(A));
    return Result;  // 返回计算出的长度
}

// 使用最小点和最大点创建矩形
inline rectangle2 RectMinMax(v2 Min, v2 Max) {
    rectangle2 Result;  // 创建一个新的矩形结构体
    Result.Min = Min;   // 设置矩形的最小点
    Result.Max = Max;   // 设置矩形的最大点
    return Result;      // 返回构造的矩形
}

// 使用最小点和尺寸（Dim）创建矩形
inline rectangle2 RectMinDim(v2 Min, v2 Dim) {
    rectangle2 Result;       // 创建一个新的矩形结构体
    Result.Min = Min;        // 设置矩形的最小点
    Result.Max = Min + Dim;  // 最大点为最小点加上尺寸
    return Result;           // 返回构造的矩形
}

// 使用中心点（Center）和半尺寸（HalfDim）创建矩形
inline rectangle2 RectCenterHalfDim(v2 Center, v2 HalfDim) {
    rectangle2 Result;              // 创建一个新的矩形结构体
    Result.Min = Center - HalfDim;  // 最小点为中心点减去半尺寸
    Result.Max = Center + HalfDim;  // 最大点为中心点加上半尺寸
    return Result;                  // 返回构造的矩形
}

// 使用中心点（Center）和尺寸（Dim）创建矩形
inline rectangle2 RectCenterDim(v2 Center, v2 Dim) {
    rectangle2 Result = RectCenterHalfDim(Center, 0.5f * Dim);
    return Result;  // 返回构造的矩形
}

// 判断一个点（Test）是否在矩形内
inline bool32 IsInRectangle(rectangle2 Rectangle, v3 Test) {
    // 检查点是否在矩形的最小值和最大值之间
    bool32 Result = ((Test.x >= Rectangle.Min.x) &&  // 测试点X坐标是否大于等于矩形的最小X坐标
                     (Test.y >= Rectangle.Min.y) &&  // 测试点Y坐标是否大于等于矩形的最小Y坐标
                     (Test.x < Rectangle.Max.x) &&  // 测试点X坐标是否小于矩形的最大X坐标
                     (Test.y < Rectangle.Max.y));  // 测试点Y坐标是否小于矩形的最大Y坐标
    return Result;                                 // 返回结果，表示点是否在矩形内
}

// 判断一个点（Test）是否在矩形内
inline bool32 IsInRectangle(rectangle2 Rectangle, v2 Test) {
    // 检查点是否在矩形的最小值和最大值之间
    bool32 Result = ((Test.x >= Rectangle.Min.x) &&  // 测试点X坐标是否大于等于矩形的最小X坐标
                     (Test.y >= Rectangle.Min.y) &&  // 测试点Y坐标是否大于等于矩形的最小Y坐标
                     (Test.x < Rectangle.Max.x) &&  // 测试点X坐标是否小于矩形的最大X坐标
                     (Test.y < Rectangle.Max.y));  // 测试点Y坐标是否小于矩形的最大Y坐标
    return Result;                                 // 返回结果，表示点是否在矩形内
}

// 获取矩形的最小角（左下角）
inline v2 GetMinCorner(rectangle2 Rect) {
    // 返回矩形的最小角，即左下角的坐标
    v2 Result = Rect.Min;
    return Result;
}

// 获取矩形的最大角（右上角）
inline v2 GetMaxCorner(rectangle2 Rect) {
    // 返回矩形的最大角，即右上角的坐标
    v2 Result = Rect.Max;
    return Result;
}

inline v2 GetDim(rectangle2 Rect) {
    v2 Result = Rect.Max - Rect.Min;
    return Result;
}

// 获取矩形的中心点
inline v2 GetCenter(rectangle2 Rect) {
    // 通过计算最小角和最大角的中点来获得矩形的中心
    v2 Result = 0.5f * (Rect.Min + Rect.Max);
    return Result;
}

// 函数：AddRadiusTo
// 描述：将给定的半径添加到矩形 A 的各个边缘，以扩展矩形的尺寸
// 返回：扩展后的矩形（Result）
inline rectangle2 AddRadiusTo(rectangle2 A, v2 Radius) {
    // 创建一个新的矩形对象 Result，用于存储扩展后的结果
    rectangle2 Result;

    // 将矩形 A 的最小值（Min）按水平和垂直方向的半径值缩小
    Result.Min = A.Min - Radius;

    // 将矩形 A 的最大值（Max）按水平和垂直方向的半径值扩展
    Result.Max = A.Max + Radius;

    // 返回扩展后的矩形 Result
    return Result;
}

inline bool32 RectanglesIntersect(rectangle2 A, rectangle2 B) {
    bool32 Result = !((B.Max.x <= A.Min.x) ||  // 如果B矩形的右侧在A矩形的左侧外部
                      (B.Min.x >= A.Max.x) ||  // 如果B矩形的左侧在A矩形的右侧外部
                      (B.Max.y <= A.Min.y) ||  // 如果B矩形的上侧在A矩形的下侧外部
                      (B.Min.y >= A.Max.y));   // 如果B矩形的下侧在A矩形的上侧外部
    // 如果没有任何不重叠的轴，则返回 true，表示两个矩形有重叠
    return Result;
}

inline bool32 RectanglesIntersectOpen(rectangle2 A, rectangle2 B) {
    bool32 Result = !((B.Max.x <= A.Min.x) ||  // 如果B矩形的右侧在A矩形的左侧外部
                      (B.Min.x >= A.Max.x) ||  // 如果B矩形的左侧在A矩形的右侧外部
                      (B.Max.y <= A.Min.y) ||  // 如果B矩形的上侧在A矩形的下侧外部
                      (B.Min.y >= A.Max.y));   // 如果B矩形的下侧在A矩形的上侧外部
    // 如果没有任何不重叠的轴，则返回 true，表示两个矩形有重叠
    return Result;
}

struct rectangle2i {
    int32 MinX, MinY;
    int32 MaxX, MaxY;
};

inline int32 GetWidth(rectangle2i A) {
    int32 Result = A.MaxX - A.MinX;
    return Result;
}

inline int32 GetHeight(rectangle2i A) {
    int32 Result = A.MaxY - A.MinY;
    return Result;
}
// 使用最小点和最大点创建矩形
inline rectangle3 RectMinMax(v3 Min, v3 Max) {
    rectangle3 Result;  // 创建一个新的矩形结构体
    Result.Min = Min;   // 设置矩形的最小点
    Result.Max = Max;   // 设置矩形的最大点
    return Result;      // 返回构造的矩形
}

// 使用最小点和尺寸（Dim）创建矩形
inline rectangle3 RectMinDim(v3 Min, v3 Dim) {
    rectangle3 Result;       // 创建一个新的矩形结构体
    Result.Min = Min;        // 设置矩形的最小点
    Result.Max = Min + Dim;  // 最大点为最小点加上尺寸
    return Result;           // 返回构造的矩形
}

// 使用中心点（Center）和半尺寸（HalfDim）创建矩形
inline rectangle3 RectCenterHalfDim(v3 Center, v3 HalfDim) {
    rectangle3 Result;              // 创建一个新的矩形结构体
    Result.Min = Center - HalfDim;  // 最小点为中心点减去半尺寸
    Result.Max = Center + HalfDim;  // 最大点为中心点加上半尺寸
    return Result;                  // 返回构造的矩形
}

// 使用中心点（Center）和尺寸（Dim）创建矩形
inline rectangle3 RectCenterDim(v3 Center, v3 Dim) {
    rectangle3 Result = RectCenterHalfDim(Center, 0.5f * Dim);
    return Result;  // 返回构造的矩形
}

// 判断一个点（Test）是否在矩形内
inline bool32 IsInRectangle(rectangle3 Rectangle, v3 Test) {
    // 检查点是否在矩形的最小值和最大值之间
    bool32 Result = ((Test.x >= Rectangle.Min.x) &&  // 测试点X坐标是否大于等于矩形的最小X坐标
                     (Test.y >= Rectangle.Min.y) &&  // 测试点Y坐标是否大于等于矩形的最小Y坐标
                     (Test.z >= Rectangle.Min.z) &&
                     (Test.x < Rectangle.Max.x) &&  // 测试点X坐标是否小于矩形的最大X坐标
                     (Test.y < Rectangle.Max.y) &&  // 测试点Y坐标是否小于矩形的最大Y坐标
                     (Test.z < Rectangle.Max.z));
    return Result;  // 返回结果，表示点是否在矩形内
}

inline v3 Lerp(v3 A, real32 t, v3 B) {
    v3 Result = (1.0f - t) * A + t * B;
    return Result;
}

// 标准化函数，用于标准化一个三维向量
inline v3 Normalize(v3 A) {
    // 通过将向量的每个分量乘以其长度的倒数来标准化
    v3 Result = A * (1.0f / Length(A));
    // 返回标准化后的向量
    return Result;
}

inline v3 NOZ(v3 A) {
    v3 Result = {};
    real32 LenSq = LengthSq(A);
    if (LenSq > Square(0.0001f)) {
        Result = A * (1.0f / SquareRoot(LenSq));
    }
    return Result;
}

// 获取矩形的最小角（左下角）
inline v3 GetMinCorner(rectangle3 Rect) {
    // 返回矩形的最小角，即左下角的坐标
    v3 Result = Rect.Min;
    return Result;
}

// 获取矩形的最大角（右上角）
inline v3 GetMaxCorner(rectangle3 Rect) {
    // 返回矩形的最大角，即右上角的坐标
    v3 Result = Rect.Max;
    return Result;
}

// 获取矩形的中心点
inline v3 GetCenter(rectangle3 Rect) {
    // 通过计算最小角和最大角的中点来获得矩形的中心
    v3 Result = 0.5f * (Rect.Min + Rect.Max);
    return Result;
}

// 函数：AddRadiusTo
// 描述：将给定的半径添加到矩形 A 的各个边缘，以扩展矩形的尺寸
// 返回：扩展后的矩形（Result）
inline rectangle3 AddRadiusTo(rectangle3 A, v3 Radius) {
    // 创建一个新的矩形对象 Result，用于存储扩展后的结果
    rectangle3 Result;

    // 将矩形 A 的最小值（Min）按水平和垂直方向的半径值缩小
    Result.Min = A.Min - Radius;

    // 将矩形 A 的最大值（Max）按水平和垂直方向的半径值扩展
    Result.Max = A.Max + Radius;

    // 返回扩展后的矩形 Result
    return Result;
}

// 函数：Offset
// 说明：将传入的矩形 A 进行偏移操作，返回新的矩形。
// 参数：
//   - A：要进行偏移的矩形。
//   - Offset：偏移量，表示矩形需要移动的距离。
// 返回值：
//   - 返回一个新的矩形，经过偏移后的最小点和最大点。
inline rectangle3 Offset(rectangle3 A, v3 Offset) {
    rectangle3 Result;
    // 对矩形的最小点和最大点分别加上偏移量
    Result.Min = A.Min + Offset;
    Result.Max = A.Max + Offset;
    return Result;  // 返回经过偏移后的矩形
}

inline rectangle2 Offset(rectangle2 A, v2 Offset) {
    rectangle2 Result;
    // 对矩形的最小点和最大点分别加上偏移量
    Result.Min = A.Min + Offset;
    Result.Max = A.Max + Offset;
    return Result;  // 返回经过偏移后的矩形
}

inline rectangle2i Offset(rectangle2i A, int32 X, int32 Y) {
    rectangle2i Result = A;
    Result.MinX += X;
    Result.MaxX += X;
    Result.MinY += Y;
    Result.MaxY += Y;
    return Result;
}

inline v3 GetDim(rectangle3 Rect) {
    v3 Result = Rect.Max - Rect.Min;
    return Result;
}

// 函数: RectanglesIntersect
// 描述:
// 检查两个矩形是否相交。矩形是三维的，通过比较它们在每个轴上的最小和最大边界来判断是否重叠。
// 输入:
//      A: 第一个矩形
//      B: 第二个矩形
// 输出:
//      如果两个矩形相交，则返回 true；否则返回 false。
inline bool32 RectanglesIntersect(rectangle3 A, rectangle3 B) {
    // 判断是否存在不重叠的情况。如果存在不重叠的轴，则返回 false。
    bool32 Result = !((B.Max.x <= A.Min.x) ||  // 如果B矩形的右侧在A矩形的左侧外部
                      (B.Min.x >= A.Max.x) ||  // 如果B矩形的左侧在A矩形的右侧外部
                      (B.Max.y <= A.Min.y) ||  // 如果B矩形的上侧在A矩形的下侧外部
                      (B.Min.y >= A.Max.y) ||  // 如果B矩形的下侧在A矩形的上侧外部
                      (B.Max.z <= A.Min.z) ||  // 如果B矩形的前侧在A矩形的后侧外部
                      (B.Min.z >= A.Max.z));   // 如果B矩形的后侧在A矩形的前侧外部
    // 如果没有任何不重叠的轴，则返回 true，表示两个矩形有重叠
    return Result;
}

// 安全比例函数，接受一个分子、一个分母和一个预设值N。
// 如果分母不为零，则执行分子除以分母的操作，
// 否则返回预设值N，避免除零错误。
inline real32 SafeRatioN(real32 Numerator, real32 Divisor, real32 N) {
    real32 Result = N;                 // 默认返回预设值N
    if (Divisor != 0.0f) {             // 如果分母不为零
        Result = Numerator / Divisor;  // 执行正常的除法运算
    }
    return Result;  // 返回结果
}

// 安全比例函数，默认返回0作为预设值，调用SafeRatioN函数进行处理。
inline real32 SafeRatio0(real32 Numerator, real32 Divisor) {
    real32 Result = SafeRatioN(Numerator, Divisor, 0);  // 使用0作为预设值
    return Result;                                      // 返回结果
}

// 安全比例函数，默认返回1作为预设值，调用SafeRatioN函数进行处理。
inline real32 SafeRatio1(real32 Numerator, real32 Divisor) {
    real32 Result = SafeRatioN(Numerator, Divisor, 1);  // 使用1作为预设值
    return Result;                                      // 返回结果
}

// 获取点P在三维矩形A中的归一化坐标（即从0到1的范围）
inline v3 GetBarycentric(rectangle3 A, v3 P) {
    v3 Result;

    // 计算P在X轴上的归一化坐标
    Result.x = SafeRatio0((P.x - A.Min.x), (A.Max.x - A.Min.x));

    // 计算P在Y轴上的归一化坐标
    Result.y = SafeRatio0((P.y - A.Min.y), (A.Max.y - A.Min.y));

    // 计算P在Z轴上的归一化坐标
    Result.z = SafeRatio0((P.z - A.Min.z), (A.Max.z - A.Min.z));

    // 返回归一化坐标
    return Result;
}

// 获取点P在三维矩形A中的归一化坐标（即从0到1的范围）
inline v2 GetBarycentric(rectangle2 A, v2 P) {
    v2 Result;

    // 计算P在X轴上的归一化坐标
    Result.x = SafeRatio0((P.x - A.Min.x), (A.Max.x - A.Min.x));

    // 计算P在Y轴上的归一化坐标
    Result.y = SafeRatio0((P.y - A.Min.y), (A.Max.y - A.Min.y));

    // 返回归一化坐标
    return Result;
}

// Lerp - 线性插值函数
// A: 起始值
// t: 插值因子，介于0到1之间，表示在A和B之间的位置比例
// B: 结束值
// 返回值: 在A和B之间的插值结果，依据t的值在A和B之间加权
inline real32 Lerp(real32 A, real32 t, real32 B) {
    // 计算线性插值：根据t的值在A和B之间按比例计算结果
    real32 Result = (1.0f - t) * A + t * B;
    return Result;  // 返回计算结果
}

//
// 重载二元运算符 * 实现向量与标量的乘法
inline v4 operator*(v4 A, real32 B) {
    v4 Result;
    Result.x = B * A.x;
    Result.y = B * A.y;
    Result.z = B * A.z;
    Result.w = B * A.w;
    return Result;
}

// 重载二元运算符 * 实现标量与向量的乘法
inline v4 operator*(real32 A, v4 B) {
    v4 Result;
    Result.x = A * B.x;
    Result.y = A * B.y;
    Result.z = A * B.z;
    Result.w = A * B.w;
    return Result;
}

// 重载二元运算符 * 实现标量与向量的乘法
inline v4 operator*(v4 A, v4 B) {
    v4 Result;
    Result.x = A.x * B.x;
    Result.y = A.y * B.y;
    Result.z = A.z * B.z;
    Result.w = A.w * B.w;
    return Result;
}

// 重载 *= 运算符，实现向量与标量的乘法赋值
inline v4& operator*=(v4& A, real32 B) {
    A = A * B;  // 复用已定义的乘法操作
    return A;
}

// 重载一元运算符 - 实现向量取反
inline v4 operator-(v4 A) {
    v4 Result;
    Result.x = -A.x;
    Result.y = -A.y;
    Result.z = -A.z;
    Result.w = -A.w;
    return Result;
}

// 重载二元运算符 + 实现向量与向量的加法
inline v4 operator+(v4 A, v4 B) {
    v4 Result;
    Result.x = A.x + B.x;
    Result.y = A.y + B.y;
    Result.z = A.z + B.z;
    Result.w = A.w + B.w;
    return Result;
}

// 重载二元运算符 + 实现标量与向量的加法
inline v4 operator+(real32 A, v4 B) {
    v4 Result;
    Result.x = A + B.x;
    Result.y = A + B.y;
    Result.z = A + B.z;
    Result.w = A + B.w;
    return Result;
}

// 重载 += 运算符，实现向量与标量的加法赋值
inline v4& operator+=(v4& A, real32 B) {
    A = B + A;  // 复用已定义的加法操作
    return A;
}

// 重载 += 运算符，实现向量与向量的加法赋值
inline v4& operator+=(v4& A, v4 B) {
    A = B + A;  // 复用已定义的加法操作
    return A;
}

// 重载二元运算符 - 实现向量与向量的减法
inline v4 operator-(v4 A, v4 B) {
    v4 Result;
    Result.x = A.x - B.x;
    Result.y = A.y - B.y;
    Result.z = A.z - B.z;
    Result.w = A.w - B.w;

    return Result;
}

// 定义一个内联函数 Hadamard，用于计算两个二维向量的阿达玛积（对应分量相乘）。
inline v4 Hadamard(v4 A, v4 B) {
    // 定义结果向量 Result，其 X 分量为 A.x * B.x，Y 分量为 A.y * B.y。
    v4 Result = {A.x * B.x, A.y * B.y, A.z * B.z, A.w * B.w};

    // 返回计算结果的二维向量 Result。
    return Result;
}

// 计算两个向量的内积
inline real32 Inner(v4 A, v4 B) {
    // 计算A的X分量与B的X分量的乘积
    // 然后加上A的Y分量与B的Y分量的乘积
    real32 Result = A.x * B.x + A.y * B.y + A.z * B.z + A.w * B.w;

    // 返回内积的结果
    return Result;
}

inline real32 LengthSq(v4 A) {
    //   这个函数计算向量 A 的长度的平方（即 A
    //   的模的平方），而不是完整的模数。计算长度的平方有时比计算长度本身更高效，因为它避免了求平方根的开销。
    // 使用内积公式：
    //   |A|^2 = A.x^2 + A.y^2 + A.z^2
    //   其中 A.x , A.y, A.z 分别是向量 A 的 x , y,z 坐标。
    real32 Result = Inner(A, A);
    return Result;
}

// Length函数用于计算二维向量A的长度（即大小或幅度）。
inline real32 Length(v4 A) {
    // 计算向量A的平方长度的平方根
    // LengthSq(A)返回向量的平方长度，取平方根即可得到实际的长度
    real32 Result = SquareRoot(LengthSq(A));
    return Result;  // 返回计算出的长度
}
// 线性插值函数，返回A和B之间的加权平均值，根据t的值插值，t为0时返回A，t为1时返回B
inline v4 Lerp(v4 A, real32 t, v4 B) {
    v4 Result = (1.0f - t) * A + t * B;  // 计算插值结果
    return Result;
}

inline real32 Sin01(real32 t) {
    real32 Result = Sin((1.0f / Pi32) * t);
    return Result;
}

inline real32 Triangle01(real32 t) {
    real32 Result = 2.0f * t;
    if (Result > 1.0f) {
        Result = 2.0f - Result;
    }
    return Result;
}

// 将二维向量XY和实数Z转换为三维向量v3
inline v3 ToV3(v2 XY, real32 Z) {
    v3 Result;
    Result.xy = XY;  // 将XY分配给Result的xy部分
    Result.z = Z;    // 将Z分配给Result的z部分
    return Result;
}

// 将三维向量XYZ和实数W转换为四维向量v4
inline v4 ToV4(v3 XYZ, real32 W) {
    v4 Result;
    Result.xyz = XYZ;  // 将XYZ分配给Result的xyz部分
    Result.w = W;      // 将W分配给Result的w部分
    return Result;
}

// 限制值在 Min 和 Max 之间的范围
inline real32 Clamp(real32 Min, real32 Value, real32 Max) {
    real32 Result = Value;
    // 如果值小于最小值，则返回最小值
    if (Result < Min) {
        Result = Min;
    }
    // 如果值大于最大值，则返回最大值
    else if (Result > Max) {
        Result = Max;
    }
    return Result;
}

// 将值限制在 0 到 1 的范围之间
inline real32 Clamp01(real32 Value) {
    // 使用 Clamp 函数来限制在 0 到 1 之间
    real32 Result = Clamp(0, Value, 1);
    return Result;
}

// 限制一个二维向量的每个分量在 0 到 1 之间
inline v2 Clamp01(v2 Value) {
    v2 Result = {Clamp(0, Value.x, 1),   // 限制 X 分量
                 Clamp(0, Value.y, 1)};  // 限制 Y 分量
    return Result;
}

// 限制一个三维向量的每个分量在 0 到 1 之间
inline v3 Clamp01(v3 Value) {
    v3 Result = {Clamp(0, Value.x, 1),   // 限制 X 分量
                 Clamp(0, Value.y, 1),   // 限制 Y 分量
                 Clamp(0, Value.z, 1)};  // 限制 Z 分量
    return Result;
}

// 将给定值 t 映射到 [Min, Max] 范围内，并将结果标准化到 [0, 1] 范围。
// 如果 t 超出了 Min 和 Max 的范围，则会被限制在 [0, 1] 范围内。
inline real32 ClampMapToRange(real32 Min, real32 t, real32 Max) {
    real32 Result{};  // 存储最终计算的结果
    // 计算给定范围的大小
    real32 Range = Max - Min;
    // 如果范围不等于0，进行映射和标准化
    if (Range != 0) {
        // 将 t 映射到 [0, 1] 范围内，并通过 Clamp01 函数保证结果在 [0, 1] 之间
        Result = Clamp01((t - Min) / Range);
    }
    // 返回计算得到的结果
    return Result;
}

// 将一个三维矩形（rectangle3）转换为二维矩形（rectangle2）
// 只保留Min和Max的xy坐标，忽略z轴信息
inline rectangle2 ToRectangleXY(rectangle3 A) {
    rectangle2 Result;
    Result.Min = A.Min.xy;  // 只提取A.Min的xy坐标赋值给Result.Min
    Result.Max = A.Max.xy;  // 只提取A.Max的xy坐标赋值给Result.Max
    return Result;          // 返回转换后的二维矩形
}

inline rectangle2i Intersect(rectangle2i A, rectangle2i B) {
    rectangle2i Result;
    Result.MinX = (A.MinX > B.MinX) ? A.MinX : B.MinX;
    Result.MaxX = (A.MaxX < B.MaxX) ? A.MaxX : B.MaxX;
    Result.MinY = (A.MinY > B.MinY) ? A.MinY : B.MinY;
    Result.MaxY = (A.MaxY < B.MaxY) ? A.MaxY : B.MaxY;
    return Result;
}

inline rectangle2i Union(rectangle2i A, rectangle2i B) {
    rectangle2i Result;
    Result.MinX = (A.MinX < B.MinX) ? A.MinX : B.MinX;
    Result.MaxX = (A.MaxX > B.MaxX) ? A.MaxX : B.MaxX;
    Result.MinY = (A.MinY < B.MinY) ? A.MinY : B.MinY;
    Result.MaxY = (A.MaxY > B.MaxY) ? A.MaxY : B.MaxY;
    return Result;
}

inline rectangle2 Union(rectangle2 A, rectangle2 B) {
    rectangle2 Result;
    Result.Min.x = (A.Min.x < B.Min.x) ? A.Min.x : B.Min.x;
    Result.Max.x = (A.Max.x > B.Max.x) ? A.Max.x : B.Max.x;
    Result.Min.y = (A.Min.y < B.Min.y) ? A.Min.y : B.Min.y;
    Result.Max.y = (A.Max.y > B.Max.y) ? A.Max.y : B.Max.y;
    return Result;
}

inline uint32 GetClampedRectArea(rectangle2i A) {
    int32 Width = (A.MaxX - A.MinX);
    int32 Height = (A.MaxY - A.MinY);
    uint32 Result = 0;
    if ((Width > 0) && (Height > 0)) {
        Result = Width * Height;
    }
    return Result;
}

inline bool32 HasArea(rectangle2i A) {
    bool32 Result = ((A.MinX < A.MaxX) && (A.MinY < A.MaxY));
    return Result;
}

inline rectangle2i InvertedInfinityRectangle2i(void) {
    rectangle2i Result;
    Result.MinX = Result.MinY = INT_MAX;
    Result.MaxX = Result.MaxY = -INT_MAX;
    return Result;
}

inline rectangle2 InvertedInfinityRectangle2(void) {
    rectangle2 Result;
    Result.Min.x = Result.Min.y = Real32Maximum;
    Result.Max.x = Result.Max.y = -Real32Maximum;
    return Result;
}

// 将sRGB255色彩值转换为线性亮度空间（0-1范围）
// 参数C是输入的颜色值，范围是0-255
inline v4 SRGB255ToLinear1(v4 C) {
    v4 Result;

    // 计算每个颜色通道的反255值，用于将颜色值从0-255范围转换为0-1范围
    real32 Inv255 = 1.0f / 255.0f;

    // 将每个颜色通道从sRGB空间转换为线性空间，并进行平方运算
    // 由于sRGB到线性空间的转换是平方，所以使用Square函数处理每个颜色通道
    Result.r = Square(Inv255 * C.r);  // 红色通道
    Result.g = Square(Inv255 * C.g);  // 绿色通道
    Result.b = Square(Inv255 * C.b);  // 蓝色通道

    // Alpha通道只是按比例缩放，保持线性
    Result.a = Inv255 * C.a;  // Alpha通道

    return Result;
}

// 将线性亮度空间（0-1范围）转换回sRGB255色彩值
// 参数C是输入的线性空间颜色值，范围是0-1
inline v4 Linear1ToSRGB255(v4 C) {
    v4 Result;

    // 计算每个颜色通道的255倍数，用于将颜色值从0-1范围转换回0-255范围
    real32 One255 = 255.0f;

    // 将每个颜色通道从线性空间转换回sRGB空间，并进行平方根运算
    // 由于线性空间到sRGB的转换是平方根，所以使用SquareRoot函数处理每个颜色通道
    Result.r = One255 * SquareRoot(C.r);  // 红色通道
    Result.g = One255 * SquareRoot(C.g);  // 绿色通道
    Result.b = One255 * SquareRoot(C.b);  // 蓝色通道

    // Alpha通道保持不变
    Result.a = One255 * C.a;  // Alpha通道

    return Result;
}

// 该函数用于将压缩的法线数据（范围为0到255）解压缩并转换到[-1, 1]范围，同时处理粗糙度（W分量）
inline v4 UnscaleAndBiasNormal(v4 Normal) {
    v4 Result;

    // 计算将[0, 255]范围的数值转换为[0, 1]范围的反向常量
    real32 Inv255 = 1.0f / 255.0f;

    // 将Normal.x从[0, 255]范围转换为[-1, 1]范围
    Result.x = -1.0f + 2.0f * (Inv255 * Normal.x);

    // 将Normal.y从[0, 255]范围转换为[-1, 1]范围
    Result.y = -1.0f + 2.0f * (Inv255 * Normal.y);

    // 将Normal.z从[0, 255]范围转换为[-1, 1]范围
    Result.z = -1.0f + 2.0f * (Inv255 * Normal.z);

    // W分量（粗糙度）已经在[0, 1]范围内，无需进一步缩放
    Result.w = Inv255 * Normal.w;

    // 返回转换后的法线值
    return Result;
}
inline v2 Arm2(real32 Angle) {
    v2 Result = {Cos(Angle), Sin(Angle)};
    return Result;
}

inline real32 ClampAboveZero(real32 Value) {
    real32 Result = (Value < 0) ? 0.0f : Value;
    return Result;
}

inline real32 GetArea(rectangle2 A) {
    v2 Dim = GetDim(A);
    real32 Result = Dim.x * Dim.y;
    return Result;
}

#endif